#pragma once
#include <vector>
#include <string>
#include <boost/shared_ptr.hpp>
#include "Exceptions.h"
#include "User.h"
#include "Storage.h"
#include "Group.h"

using namespace std;

typedef uint32_t THANDLE;

namespace CSApi
{
	/**
	 Klasa reprezentująca metody możliwe do realizacji po stronie klienta. 
	 */
	class ClientApi {
	public:
		virtual ~ClientApi();

		/**
		 * Metoda sprawdzająca czy plik o podanej scieżce istnieje
		 * @param path scieżka do pliku
		 * @return true jeżeli plik istnieje, false jeżeli nie istnieje
		 */
		virtual bool FileExists(const std::string &path) = 0;
		
		/**
		 * Otwiera plik o podanych atrybutach
		 * @param path scieżka do pliku
		 * @param mode typ otwarcia tożsame z fopen()
		 * @return uchwyt do otwartego pliku 
		 */
		virtual THANDLE FileOpen(const std::string &path, const std::string &mode) = 0;
		
		/**
		 * Zamyka plik
		 * @param handle uchwyt pliku
		 * @return true jeżeli udało się poprawnie zamknąć plik, false jeżeli nie udało się zamknąć
		 */
		virtual bool FileClose(THANDLE handle) = 0;
		
		/**
		 * Pobiera rozmiar pliku
		 * @param handle uchwyt do pliku
		 * @return rozmiar pliku
		 */
		virtual uint64_t FileSize(THANDLE handle) = 0;
		
		/**
		 * Pobiera pozycję w pliku
		 * @param handle uchwyt do pliku
		 * @return pozycja w pliku
		 */
		virtual uint64_t FileTell(THANDLE handle) = 0;
		
		/**
		 * Pobiera czas pliku
		 * @param handle uchwyt do pliku
		 * @return Timestamp pliku
		 */
		virtual uint64_t FileTimestamp(THANDLE handle) = 0;
		
		/**
		 * Sprawdza czy pozycja kursora w pliku jest na końcu
		 * @param handle uchwyt do pliku
		 * @return true - jeżeli kursor znajduję się na końcu pliku, false w przeciwnym wypadku
		 */
		virtual bool FileEof(THANDLE handle) = 0;
		
		/**
		 * Zmienia pozycję kursora na pliku
		 * @param handle uchwyt do pliku
		 * @param position nowa pozycja kursora
		 * @return true jeżeli operacja udała się, false jeżeli nie
		 */
		virtual bool FileSeek(THANDLE handle, int64_t position /*-1 for end*/) = 0;
		
		/**
		 * Zapisuję dane do pliku
		 * @param handle uchwyt do pliku
		 * @param size rozmiar danych
		 * @param data dane do zapisania w pliku
		 * @return zwraca ilość zapisanych danych
		 */
		virtual uint32_t FileWrite(THANDLE handle, uint32_t size, const uint8_t *data) = 0;
		
		/**
		 * Odczytuję zawartość pliku
		 * @param handle uchwyt do pliku
		 * @param size ilość danych do przeczytania
		 * @param data buffor do zapisu
		 * @return  ilość od czytanych danych
		 */
		virtual uint32_t FileRead(THANDLE handle, uint32_t size, uint8_t *data) = 0;
		
		/**
		 * Usuwa plik w danej lokalizacji
		 * @param path scieżka do pliku
		 * @return true jeżeli udało się usunąć plik, false jeżeli nie udało się usunąć
		 */
		virtual bool FileDelete(const std::string &path) = 0;

		/**
		 * Zmienia nazwę pliku
		 * @param fileId identyfikator pliku
		 * @param name nowa nazwa pliku
		 * @return staus operacji
		 */
		virtual int32_t RenameFile(uint32_t fileId, string name) = 0;

		/**
		 * Tworzy katalog
		 * @param folderId identyfikator folderu w którym zostanie stworzony katalog
		 * @param name nazwa nowo powstałego katalogu
		 * @return identyfikator nowo powstałego katalogu
		 */
		virtual int32_t MakeDirectory(uint32_t folderId, string name) = 0;
		
		/**
		 * Usuwa katalog 
		 * @param folderId identyfikator folderu
		 * @return status operacji
		 */
		virtual int32_t DeleteDirectory(uint32_t folderId) = 0;
		
		/**
		 * Zmienia nazwę katalogu
		 * @param folderId identyfikator folderu
		 * @param name nowa nazwa folderu
		 * @return status operacji
		 */
		virtual int32_t RenameDirectory(uint32_t folderId, string name) = 0;

		/**
		 * Dodaje użytkownika
		 * @param name nazwa użytkownika
		 * @param password hasło użytkownika
		 * @return identyfikator użytkownia jeżeli udał się go utworzyć, 0 - jeżeli błąd
		 */
		virtual int32_t AddUser(string name, string password) = 0;
		
		/**
		 * Usuwa użytkownika
		 * @param userId identyfikator użtkownika
		 * @return indentyfikator użytkownika 
		 */
		virtual int32_t RemoveUser(uint32_t userId) = 0;
		
		/**
		 * Zmiana hasła użytkownika
		 * @param name nazwa użytkownika
		 * @param password hasło użytkownika
		 * @return identyfikator użytkownika
		 */
		virtual int32_t ChangeUserPassword(string name, string password) = 0;
		
		/**
		 * Pobiera listę użytkowników
		 * @return lista użytkowników
		 */
		virtual vector<User> GetUsersList() = 0;

		/**
		 * Dodaję grupę
		 * @param name nazwa grupy
		 * @return identyfikator utworzonej grupy
		 */
		virtual int32_t AddGroup(string name) = 0;
		
		/**
		 * Usuwa grupę
		 * @param groupId identyfikator grupy
		 * @return status operacji
		 */
		virtual int32_t RemoveGroup(uint32_t groupId) = 0;
		
		/**
		 * Pobiera listę grup
		 * @return lista grup
		 */
		virtual vector<Group> GetGroupList() = 0;

		/**
		 * Dodaję magazyn
		 * @param name nazwa magazynu
		 * @param key klucz
		 * @return 
		 */
		virtual int32_t AddStorage(string name, string key) = 0;
		
		/**
		 * Usuwa magazyn
		 * @param storageId identyfikator magazynu
		 * @return identyfikator usuniętego magazynu
		 */
		virtual int32_t RemoveStorage(uint32_t storageId) = 0;
		
		/**
		 * Zmienia klucz magazynu
		 * @param storage nazwa magazynu
		 * @param key nowy klucz
		 * @return status operacji
		 */
		virtual int32_t ChangeStorageKey(string storage, string key) = 0;
		
		/**
		 * Pobiera listę magazynów
		 * @return lista magazynów
		 */
		virtual vector<Storage> GetStorageList() = 0;

		/**
		 * Udostępnia wskazaną sciężke
		 * @param virtualPath wirtualna scieżka
		 * @param storagePath scieżka zapisywana do magazynu
		 * @param storageName nazwa magazynu
		 * @param force wymuszenie
		 * @return status operacji
		 */
		virtual bool Share(const std::string &virtualPath, const std::string &storagePath, const std::string &storageName, bool force = false) = 0;
		
		/**
		 * Wstrzymuję udostępnianie
		 * @param virtualPath wirtualna scieżka
		 * @param remove czy usunąć
		 * @return status operacji
		 */
		virtual bool UnShare(const std::string &virtualPath, bool remove = false) = 0;
	};
	boost::shared_ptr<ClientApi> CreateClientApi(const std::string &ip, const std::string &port, const std::string &username, const std::string &password);
};

